import uuid

from django.conf import settings
from rest_framework import serializers
from rest_framework.exceptions import ValidationError

from user.models import Medicine
from libs.alipay_common import gateway, alipay

from .models import Order, OrderDetail
from patient.models import HospitalInfo
from registered.models import DetailedList


class OrderSerializer(serializers.ModelSerializer):
    # 接收一个或多个Medicine对象的主键作为输入
    medicines = serializers.PrimaryKeyRelatedField(queryset=Medicine.objects.all(), write_only=True, many=True)

    class Meta:
        model = Order
        fields = ['medicines', 'total_amount', 'subject', 'pay_type']

    # 校验价格
    def _check_price(self, attrs):
        real_price = 0
        for medicine in attrs.get('medicines'):
            real_price += int(medicine.price)
        user = HospitalInfo.objects.get(name=attrs.get('subject'))
        real_price = str(real_price + (int(user.time_length) * 50))
        if not real_price == str(int(attrs.get('total_amount'))):
            raise ValidationError('价格不一致')
        else:
            return real_price

    # 生成订单号
    def _get_trade_no(self):
        trade_no = str(uuid.uuid4())
        return trade_no

    # 获取用户
    def _get_user(self, attrs):
        name = attrs.get('subject')
        user = DetailedList.objects.all().filter(patient_name=name).first()
        return user

    #
    def _get_pay_url(self, total_amount, subject, trade_no):
        res = alipay.api_alipay_trade_page_pay(
            out_trade_no=trade_no,
            total_amount=float(total_amount),
            subject=subject,
            return_url=settings.RETURN_URL,  # get回调地址
            notify_url=settings.NOTIFY_URL  # post回调地址
        )
        pay_url = gateway + res
        return pay_url

    # 入库前的准备
    def validate(self, attrs):
        # 1校验价格,计算一下总价格和后端算出来的价格是否一致
        total_amount = self._check_price(attrs)
        # 2生成订单号
        trade_no = self._get_trade_no()
        # 3支付的用户 request.user
        user = self._get_user(attrs)
        # 4生成支付链接,放入self.context中
        pay_url = self._get_pay_url(total_amount, attrs.get('subject'), trade_no)
        # 5入库前的准备
        self.context['pay_url'] = pay_url
        attrs['user'] = user
        attrs['out_trade_no'] = trade_no

        return attrs

    def create(self, validated_data):
        medicines = validated_data.pop('medicines')
        order = Order.objects.create(**validated_data)
        for medicine in medicines:
            OrderDetail.objects.all().create(order=order, medicine=medicine, price=medicine.price)
        return order
